package cn.edu.dgut.sai.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.web.WebApplicationInitializer;

/**
 * 企业级软件开发-实训课程：Spring Boot 2.x
 *
 * @author 黎志雄
 * 2019-9-17
 * <p>
 * {@link Conditional}注解为Bean的实例化设置条件。只有里面的{@link Condition}的实现类的matches方法返回true时才实例化为Bean
 */
@Configuration
@ConditionalOnAClass(className = "org.apache.catalina.startup.Tomcat")
public class TomcatConfiguration {

    private final ServerProperties properties;

    public TomcatConfiguration(ServerProperties properties) {
        this.properties = properties;
    }

    /**
     * spring boot应用程序启动流程：
     *
     * @see SpringApplication#createApplicationContext()
     * @see AnnotationConfigServletWebServerApplicationContext
     * @see AbstractApplicationContext#refresh()
     * @see ServletWebServerApplicationContext#onRefresh()
     * @see ServletWebServerApplicationContext#createWebServer()
     * @see TomcatServletWebServerFactory#getWebServer(org.springframework.boot.web.servlet.ServletContextInitializer...) 实例化tomcat容器
     * @see ServletWebServerApplicationContext#selfInitialize(javax.servlet.ServletContext)
     * @see ServletContextInitializer 初始化tomcat容器时，会从spring容器注入所有实现了{@link ServletContextInitializer}接口的Bean,并调用它们的onStartup()方法，类似于{@link WebApplicationInitializer}的作用。但它只用于spring boot的应用程序。
     */
    @SuppressWarnings("JavadocReference")
    @Bean
    TomcatServletWebServerFactory servletContainerFactory() {
        // 使用带参的构造函数实例化TomcatServletWebServerFactory，可以自定义tomcat容器的ContextPath和port。
        //return new TomcatServletWebServerFactory(ContextPath, port);
        return new TomcatServletWebServerFactory(this.properties.getPort());
    }

}
